#ifndef _SPIFLASH_H_
#define _SPIFLASH_H_

#include "oc_rsrc_cfg.h"
#include "spi.h"
#include "gpio.h"

/* CS PIN CTRL */
#define SPIFLASH_CS_LOW()       HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET)
#define SPIFLASH_CS_HIGH()      HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET)

/* CMD for spiflash */
#define SPIFLASH_CMD_EWRSR      0x50    /* 使能写状态寄存器命令 */
#define SPIFLASH_CMD_WRSR       0x01    /* 写状态寄存器命令 */
#define SPIFLASH_CMD_RDSR       0x05    /* 读状态寄存器命令 */
#define SPIFLASH_CMD_EWR        0x06    /* 写使能命令 */
#define SPIFLASH_CMD_DISEWR     0x04    /* 禁止写, 退出AAI状态 */
#define SPIFLASH_CMD_PAGEP      0x02    /* 页编程命令 */
#define SPIFLASH_CMD_RDDT       0x03    /* 读数据区命令 */
#define SPIFLASH_CMD_RDID       0x9F    /* 读器件ID命令 */
#define SPIFLASH_CMD_SE         0x20    /* 擦除扇区 (Sector 4K) 命令 */
#define SPIFLASH_CMD_BE         0xD8    /* 擦除扇区 (Block 64KB) 命令 */
#define SPIFLASH_CMD_CE         0xC7    /* 片擦除命令 */

#define SPIFLASH_CMD_DUMMY      0x00

/* REG for spiflash */
#define SPIFLASH_REG_SR_WIP     0x01    /* SR1的Erase/Write In Progress 标志位 */

/* 定义串行 SPIFLASH ID */
enum
{
    SPIFLASH_W25Q64BV_ID    = 0xEF4017, /* BV, JV, FV */
    SPIFLASH_W25Q128_ID     = 0xEF4018
};

/* spiflash 芯片相关特性 */
typedef struct SPIFLASH_ATTR_STR
{
    uint32_t chip_id;            /* 芯片ID */
    char     chip_name[16];      /* 芯片型号字符串，主要用于显示 */
    uint32_t total_size;         /* 总容量 */
    uint32_t bank_size;          /* 块大小 */
    uint16_t sector_size;        /* 扇区大小 */
    uint16_t page_size;          /* 页大小 */
} spiflash_attr, *spiflash_attr_t;

/* spiflash 硬件操作 for mboot */
typedef struct spiflash_op_for_mboot_str
{
    hw_addr_attr * (*take_free_space)(uint32_t size);        /* 分配一片空间 */
    HW_STATUS (*erase_space)(uint32_t addr);                 /* 擦除这片空间 */
    int (*put_data)(hw_buf_attr * buf_attr, uint32_t addr);  /* 写数据 */
    hw_buf_attr * (*get_data)(uint32_t addr, uint16_t nbr);  /* 读数据 */
    void (*memory_mapped)(void);                             /* 内存映射 */
} spiflash_op_for_mboot;

/* spi 初始化 */
int spiflash_init(void);

/* 注册操作函数接口 */
spiflash_op_for_mboot *spiflash_op_for_mboot_register(void);

#endif
